package com.mokylin.dbschema.service;

import com.mokylin.dbschema.config.ConfigInfo;
import com.mokylin.dbschema.dao.DbVersionDao;
import com.mokylin.dbschema.pojo.DbVersion;
import com.mokylin.dbschema.util.ClassInfoCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 维持数据库连接心跳：定时更新dbversion表的updatetime字段
 *
 * @author 李朝(Li.Zhao)
 * @since 2015/12/14.
 */

public class DbVersionHeartBeatService {

    private static final Logger LOGGER = LoggerFactory.getLogger(DbVersionHeartBeatService.class);

    private static ScheduledExecutorService scheduledExecutorService;

    private static DbVersionDao dbVersionDao = ClassInfoCache.getSingleton(DbVersionDao.class);

    /**
     * 心跳时间间隔偏移量/容错量(秒)
     */
    private static final long HEARTBEAT_OFFSET = 60*3;

    static {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            if (scheduledExecutorService!=null && !scheduledExecutorService.isShutdown()) {
                scheduledExecutorService.shutdown();
            }
        }));
    }

    private static ScheduledExecutorService getScheduledExecutorService() {
        if (scheduledExecutorService == null || scheduledExecutorService.isShutdown()) {
            scheduledExecutorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
        }
        return scheduledExecutorService;
    }

    /**
     * 启动心跳时间定时更新
     */
    public static void start() {
        getScheduledExecutorService().scheduleAtFixedRate(() -> {
            try {
                dbVersionDao.setUpdateTime();
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
            }
        }, 0, ConfigInfo.getDbConnectHeartbeatSeconds(), TimeUnit.SECONDS);
    }

    /**
     * 停止心跳时间更新
     */
    public static void shutdown() {
        if (scheduledExecutorService!=null && !scheduledExecutorService.isShutdown()) {
            scheduledExecutorService.shutdown();
        }
    }

    /**
     * 当前更新的应用是否正在连接（心跳时间在有效范围内）
     *
     * @return
     * @throws SQLException
     */
    public static boolean isConnecting() throws SQLException {
        DbVersion dbVersion = dbVersionDao.getDbVersion();
        if (dbVersion.getUpdateTime().toInstant().plus(ConfigInfo.getDbConnectHeartbeatSeconds()+ HEARTBEAT_OFFSET, ChronoUnit.SECONDS).isAfter(Instant.now())) {
            return true;
        }
        return false;
    }

}
